//
//  @ Project : Untitled
//  @ File Name : FrameworkImp.cpp
//  @ Date : 2009/8/31
//  @ Author : 
//
//
#include "FrameworkPublic.h"
#include "FrameworkListener.h"
#include "FrameworkImp.h"
#include "ServiceReferenceImp.h"
#include "ServiceRegistrationImp.h"
#include "BundleActivator.h"  //include this for some default class function implement
#include "BundleContextImp.h"
#include "BundleImp.h"

USING_NAME_SPACE_OSGI


void FrameworkImp::init()
{
   if( m_State==Bundle::STARTING || m_State==Bundle::ACTIVE || m_State==Bundle::STOPING)
	   return;

   printf( "framework start to initial......\n" );
   char szModulePath[256] = {0};
   GetModuleFileNameA(NULL, szModulePath, 256 );
   char* pDash = strrchr(szModulePath, '\\');
   if(pDash) 
	   pDash[1]=0;
   else 
	   strcat(szModulePath, "\\" );

   m_BoundleLocationBase = szModulePath;
   // Enable event handle
   m_HandleEvent = true;

   // Reify Bundle objects for all installed bundles

   m_BundleContext = getBundleContext();
   static_cast<BundleContextImp*>(m_BundleContext)->m_Bundle = this;

   // Register any framework services. For example, PackageAdmin, ConditionalPermissionAdmin, StartLevel.
   // TODO: regist all framework service first

   m_State = Bundle::STARTING;   
   printf( "framework start to initialed.\n" );
}

void* FrameworkImp::loadClass(const char* name)
{
	return 0;
}

int FrameworkImp::start()
{
    return start(0);
}

int FrameworkImp::start(int options)
{	
	if( m_State!=Bundle::STARTING )
		init();

	printf( "framework start to start......\n" );

	for( std::vector<BundleContext*>::iterator itor = m_BundleRegistrys.begin(); itor!=m_BundleRegistrys.end(); ++itor ) {
		BundleImp* bundle = static_cast<BundleImp*>((*itor)->getBundle());
		if( bundle->getBundleId()==0 || !bundle->m_AutoStart )
			continue;
		bundle->m_ActivatorClass = static_cast<BundleActivator*>(bundle->loadClass( bundle->m_Activator.c_str() ));
		bundle->m_ActivatorClass->start( (*itor) );
	}
	m_State = Bundle::ACTIVE;
	fireFrameEvent( FrameworkEvent::STARTED, this );
	printf( "framework start to started.\n" );
	return 0;
}

int FrameworkImp::stop()
{
   return stop(0);
}

int FrameworkImp::stop(int options)
{
	printf( "framework start to stop......\n" );
	// The method returns immediately to the caller after initiating the following steps to be taken on another thread.
	m_State = Bundle::STOPING;

	// Unregister all services registered by this Framework.

	// Event handling is disabled.
	m_HandleEvent = false;

	m_State = Bundle::RESOLVED;

	// All resources held by this Framework are released. This includes threads, bundle class loaders, open files, etc.

	// Notify all threads that are waiting at waitForStop that the stop operation has completed.

	//After being stopped, this Framework may be discarded, initialized or started.
	printf( "framework start is stopped.\n" );
	
	return 0;
}

FrameworkEvent* FrameworkImp::waitForStop(long timeout)
{
	if( m_State!=Bundle::STARTING && m_State!=Bundle::ACTIVE && m_State!=Bundle::STOPING)
		return 0;

	printf( "framework start to stop......\n" );

	// TODO: complete here.

	printf( "framework start is stopped.\n" );

	/*
	A Framework Event indicating the reason this method returned. The following FrameworkEvent types may be returned by this method.
	STOPPED - This Framework has been stopped.
	STOPPED_UPDATE - This Framework has been updated which has shutdown and will now restart.
	STOPPED_BOOTCLASSPATH_MODIFIED - This Framework has been stopped and a bootclasspath extension bundle has been installed or updated. The VM must be restarted in order for the changed boot class path to take affect.
	ERROR - The Framework encountered an error while shutting down or an error has occurred which forced the framework to shutdown.
	WAIT_TIMEDOUT - This method has timed out and returned before this Framework has stopped.
	*/
	// WARNING: client must delete the FrameworkEvent object, and the new and delete must not overloaded.
	return new FrameworkEvent( FrameworkEvent::WAIT_TIMEDOUT, 0 );
}

void FrameworkImp::uninstall()
{
	// The Framework cannot be uninstalled.
	// This method always throws a BundleException.
}

int FrameworkImp::update()
{
	int ret = stop();
	if( ret!=0 )
		return ret;
	return start();
}

BundleContext* FrameworkImp::getBundleContext()
{	
	BundleContext* context = new BundleContextImp(this);
	m_BundleRegistrys.push_back( context );
	return context;
}

long FrameworkImp::getBundleId()
{
   // This Framework is assigned the unique identifier zero (0) since this Framework is also a System Bundle.
   return 0; 
}

long FrameworkImp::getLastModified()
{ 
	return 0;
}

const char* FrameworkImp::getLocation()
{
   return SYSTEM_BUNDLE_LOCATION;
}

int FrameworkImp::getState()
{
	return Bundle::ACTIVE;
}

const char* FrameworkImp::getSymbolicName()
{
   return SYSTEM_BUNDLE_SYMBOLICNAME;
}

Version& FrameworkImp::getVersion()
{
	static Version s_FrameworkVersion(1,0,0);
	return s_FrameworkVersion;
}